﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
//using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
using System.IO;
using KnowWare.Model;
using Xceed.Wpf.Toolkit;
using System.ComponentModel;
using iTextSharp.text;
using iTextSharp.text.pdf;


/**
 * Ting som mangler:
 * 
 * Når et nyt hold vælges i vores ListView skal felterne i højre side påsættes værdierne fra det valgte hold.
 * Afslut event funktion
 * "Spring over fil vindue"-knappen skal fjernes fra MainWindow (Når vi når til en eventuel demonstration)
 * Kommenter alt koden?
 **/

namespace KnowWareBeta
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class HovedWindow : Window
    {
        private Event aktuelleEvent;
        private Kategori aktuelleKategori;
        private Hold aktuelleHold;

        public HovedWindow(Event evt)
        {
            aktuelleEvent = evt;
            aktuelleKategori = aktuelleEvent.Kategorier[0];

            InitializeComponent();

            // Fylder vinduets indhold
            UISkaber();
            FyldComboBox();
            gB_hold.IsEnabled = false;
        }

        private void UISkaber()
        {
            // Først ryder vores to StackPanels for at gøre plads til det nye indhold
            sp_labels.Children.Clear();
            sp_felter.Children.Clear();

            // For at forøge bredden dynamisk er vi nødt til at sætte dennes bredde til 0 som start
            gB_hold.Width = 0;

            for (int i = 0; i < aktuelleKategori.KriterieNavn.Count; i++)
            {
                // Vi skaber en Label
                Label lb = new Label();
                lb.Name = "lbl_" + i;
                lb.Content = aktuelleKategori.KriterieNavn[i];
                sp_labels.Children.Add(lb);

                // Vi skaber nu en IntegerUpDown Control
                IntegerUpDown iup = new IntegerUpDown();
                iup.Name = "iup_" + i;
                iup.Maximum = aktuelleKategori.KriterieMax[i];
                iup.Minimum = 0;
                iup.Value = 0;
                iup.Width = 50;

                // For at få vores IntegerUpDown Control til at stå på linje med vores Label skal denne justeres lidt
                iup.Height = lb.Height;
                iup.Margin = new Thickness(6, 6, 0, 0);

                // Vi registrerer et event på vores IntegerUpDown Control,
                // for at kunne validerer brugerens input
                iup.PreviewTextInput += new TextCompositionEventHandler(iup_PreviewTextInput);

                sp_felter.Children.Add(iup);

                // Til sidst udregner vi størrelsen på bredden af vores Label og IntegerUpDown Control, samt deres margen
                int nyBredde = lb.Content.ToString().Length * 6 + 50 + 18;
                if (gB_hold.Width < nyBredde)
                {
                    // Hvis denne er laverer en vores GroupBox's bredde skal GroupBox'en udvides til den nye bredde
                    gB_hold.Width = nyBredde;
                }
            }
        }

        private void iup_PreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            int temp;

            // Vi type-caster vores sender objekt til en IntegerUpDown,
            // fordi vi ved at objektet som sender eventet må være en IntegerUpDown,
            // da eventet ikke registreres på andre Controls.
            IntegerUpDown iup = (IntegerUpDown)sender;

            // Forsøg at parse inputtet til et heltal for at se om der skrives tegn eller bogstaver
            if (!int.TryParse(e.Text, out temp))
            {
                // Fortæl at eventet er blevet håndteret,
                // således at feltet ikke modtager inputtet
                e.Handled = true;
            }
            else
            {
                try
                {
                    // Undersøg om teksten i feltet overskrider maximum værdien for vores Control
                    if (int.Parse(iup.Text) > iup.Maximum)
                    {
                        // Fortæl at eventet er blevet håndteret,
                        // således at feltet ikke modtager inputtet
                        e.Handled = true;
                    }
                }
                catch (Exception)
                {
                    e.Handled = false;
                }
            }
        }

        private void FyldComboBox()
        {
            foreach (Kategori kategori in aktuelleEvent.Kategorier)
            {
                // Tilføj kategorien til vores ComboBox.
                // Dennes label findes ved klassens ToString() metode
                cb_kategori.Items.Add(kategori);
            }
            // Vælg den første kategori i vores ComboBox (blot for at vælge en)
            cb_kategori.SelectedIndex = 0;
        }

        /**
         * De viste værdier i vores ListView genereres ud fra Bindings i XAML-koden.
         * Disse bindings specificerer hvilke properties fra objektet som skal bruges til hver
         * enkelt kolonne. 
         **/
        private void ListviewFiller(Kategori kategori)
        {
            // Først rydes vores ListView
            lv_holdListe.Items.Clear();

            foreach (Hold hold in kategori.HListe)
            {
                // Tilføj holdet til vores ListView

                lv_holdListe.Items.Add(hold);
            }

            SorterListView();
        }

        private void SorterListView()
        {
            // Ryd først sorteringsbeskrivelsen
            lv_holdListe.Items.SortDescriptions.Clear();

            // Dernæst fortæl listen at denne skal sortere sine items efter først PointSum og dernæst Standnummer.
            lv_holdListe.Items.SortDescriptions.Add(new SortDescription("PointSum", ListSortDirection.Descending));
            lv_holdListe.Items.SortDescriptions.Add(new SortDescription("Stand", ListSortDirection.Ascending));
        }

        private void btn_registrer_Click(object sender, RoutedEventArgs e)
        {
            // Først skal vi bruge en liste til at gemme vores indtastede værdier i
            List<int> intListe = new List<int>();

            for (int i = 0; i < aktuelleKategori.KriterieNavn.Count; i++)
            {
                // Vi type-caster vores StackPanels Controls,
                // da vi ved at der her kun findes IntegerUpDown Controls
                IntegerUpDown iup = (IntegerUpDown)sp_felter.Children[i];

                // Dennes numeriske værdi tilføjes til en liste
                intListe.Add(int.Parse(iup.Text));
            }

            // Sammenlæg de indtastede summer
            aktuelleHold.Summer(intListe);
            aktuelleHold.ErTildeltPoint = true;

            // Fyld vores ListView

            foreach (IntegerUpDown item in sp_felter.Children)
            {
                item.Text = "0";
            }

            ListviewFiller(aktuelleKategori);

            int idx = 1;
            foreach (Hold item in lv_holdListe.Items)
            {
                item.Placering = idx;
                idx++;
            }
            idx = 0;

            gB_hold.IsEnabled = false;
        }

        private void lv_holdListe_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            gB_hold.IsEnabled = true;
            aktuelleHold = (Hold)lv_holdListe.SelectedItem;

            if (lv_holdListe.SelectedItem == null)
            {
                // Hvis der ikke er valgt noget i vores ListView, sættes vores
                // GroupBox's header i højre side af vores UI til sin standardværdi
                gB_hold.Header = "Hold";
                gB_hold.IsEnabled = false;
            }
            else
            {
                // Vi type-caster det valgte element i listen til et Hold,
                // fordi vi ved at denne altid må være af typen Hold.
                aktuelleHold = (Hold)lv_holdListe.SelectedItem;

                // Når vi kender det valgte hold, kan vi finde det valgte holds kategori
                aktuelleKategori = aktuelleEvent.FindKategori(aktuelleHold.Kategori);

                // Hvis der er valgt et hold i vores ListView, sættes vores
                // GroupBox's header i højre side af vores UI til holdets navn
                gB_hold.Header = aktuelleHold.HoldNavn;

                int i = 0;
                foreach (IntegerUpDown item in sp_felter.Children)
                {
                    // Fylder vores IntegerUpDown Controls med holdets point
                    item.Value = aktuelleHold.Kriterier[i].Antal;
                    i++;
                }

                if (aktuelleHold.ErTildeltPoint == false)
                {
                    // Hvis holdet ikke er tildelt point, skal det være muligt igennem formularen
                    gB_hold.IsEnabled = true;
                    aktuelleKategori = aktuelleEvent.FindKategori(aktuelleHold.Kategori);
                    gB_hold.Header = aktuelleHold.HoldNavn;
                }
                else
                {
                    // Hvis holdet er tildelt point, skal man ikke umiddelbart kunne ændre i dettes point
                    gB_hold.IsEnabled = false;
                }
            }
        }

        private void cb_kategori_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // Kategorierne findes som referencer til objekter i vores ComboBox,
            // hvorved vi kan finde den valgte kategori ved at finde det valgte Item
            aktuelleKategori = (Kategori)cb_kategori.SelectedItem;

            // Fyld vores ListView
            ListviewFiller(aktuelleKategori);

            // Generer Højre del af vores UI
            UISkaber();
        }

        private void tb_søg_TextChanged(object sender, TextChangedEventArgs e)
        {
            string søgeStreng = tb_søg.Text;

            // Først ryder vi listen for at kunne tilføje kun de elementer som matchers søgningen
            lv_holdListe.Items.Clear();

            foreach (Hold hold in aktuelleKategori.HListe)
            {
                // Undersøg først om holdnavnet indeholder den streng vi søger efter,
                // eller om holdets standnummer starter med søgestrengen, f.eks:
                // søgeStreng = "2", viser standnumre der starter med 2: (2, 20, 200, 2000)
                if (hold.HoldNavn.ToLower().Contains(søgeStreng.ToLower()) || hold.Stand.ToString().StartsWith(søgeStreng))
                {
                    // Hvis holdet matcher søgekriterierne, så tilføjes dette til listen
                    lv_holdListe.Items.Add(hold);
                }
            }

            SorterListView();
        }

        private void RedigerPoint(object sender, RoutedEventArgs e)
        {
            // Find det valgte hold i listen
            aktuelleHold = (Hold)lv_holdListe.SelectedItem;

            // Gemmer holdets navn i en seperat variable for senere brug
            string holdnavn = aktuelleHold.HoldNavn;

            foreach (Kriterie krit in aktuelleHold.Kriterier)
            {
                // Nulstil holdets point
                krit.Antal = 0;
            }

            // Nulstil holdets point
            aktuelleHold.PointSum = 0;
            aktuelleHold.ErTildeltPoint = false;

            // Genopbyg ListView'et med det redigerede hold
            ListviewFiller(aktuelleKategori);

            // Find og vælg det hold som nu er redigerbart i vores ListView, 
            // da dette kan have ændret position i ListView'et
            foreach (Hold hold in lv_holdListe.Items)
            {
                if (hold.HoldNavn == holdnavn)
                {
                    lv_holdListe.SelectedItem = hold;
                    break; // Hvis holdet er fundet er det ikke nødvendigt at se på de andre hold
                }
            }
        }

        private void GenererDiplom(ItemCollection holdListe)
        {
            var doc = new Document();
            Paragraph para;

            // Bygger de skrifttyper som skal bruges til at generere PDF diplomet
            BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, false);
            Font Overskrift = new Font(bf, 80, Font.BOLD, BaseColor.DARK_GRAY);
            Font Tekst = new Font(bf, 19, Font.NORMAL, BaseColor.BLACK);
            Font tableFed = new Font(bf, 14, Font.BOLD, BaseColor.BLACK);
            Font lilleOverskift = new Font(bf, 18, Font.BOLDITALIC, BaseColor.BLACK);

            string sti = Directory.GetCurrentDirectory();

            PdfWriter.GetInstance(doc, new FileStream(sti + "/diplom.pdf", FileMode.Create));
            doc.Open();

            foreach (Hold hold in holdListe)
            {
                iTextSharp.text.Image logo = iTextSharp.text.Image.GetInstance(Directory.GetCurrentDirectory() + "../../../Logo.jpg");
                doc.Add(logo);

                // Overskrift
                para = new Paragraph(95, "DIPLOM", Overskrift);
                para.Alignment = Element.ALIGN_CENTER;
                para.IndentationLeft = 100;
                para.IndentationRight = 100;
                para.SpacingAfter = 40;
                doc.Add(para);

                // Eventtekst
                para = new Paragraph(35, "Virksomheden\r\n" + hold.HoldNavn, lilleOverskift);
                para.Alignment = Element.ALIGN_CENTER;
                para.IndentationRight = 100;
                para.IndentationLeft = 100;
                doc.Add(para);

                para = new Paragraph(35, "Tildeles dette diplom ", lilleOverskift);
                para.Alignment = Element.ALIGN_CENTER;
                para.IndentationRight = 100;
                para.IndentationLeft = 100;
                doc.Add(para);

                para = new Paragraph(35, " for deltagelse i:\r\n" + aktuelleEvent.Navn + ", i " + hold.Kategori + " kategorien", lilleOverskift);
                para.Alignment = Element.ALIGN_CENTER;
                //para.IndentationRight = 100;
                //para.IndentationLeft = 100;
                doc.Add(para);

                para = new Paragraph(35, aktuelleEvent.dansk(aktuelleEvent.Dato) + " d. " + aktuelleEvent.Dato.ToLongDateString(), lilleOverskift);
                para.Alignment = Element.ALIGN_CENTER;
                para.IndentationRight = 100;
                para.IndentationLeft = 100;
                doc.Add(para);

                // Ledetekst
                PdfPTable table = new PdfPTable(2);
                PdfPCell cell = new PdfPCell(new Phrase("Kriterie", tableFed));
                cell.Colspan = 1;
                table.SpacingBefore = 35;
                table.SpacingAfter = 15;
                table.AddCell(cell);

                cell = new PdfPCell(new Phrase("Point", tableFed));
                table.AddCell(cell);

                foreach (var item in hold.Kriterier)
                {
                    table.AddCell(item.Navn);
                    table.AddCell(item.Antal.ToString());
                }

                table.AddCell(new Phrase("Samlet antal: ", tableFed));
                table.AddCell(new Phrase(hold.PointSum.ToString(), tableFed));
                doc.Add(table);

                //Placering
                para = new Paragraph("Virksomheden fik en samlet placering som: " + hold.Placering, tableFed);
                para.Alignment = Element.ALIGN_CENTER;
                para.IndentationLeft = 100;
                para.IndentationRight = 100;
                doc.Add(para);

                //Sponsorbillede

                iTextSharp.text.Image sponsor = iTextSharp.text.Image.GetInstance(Directory.GetCurrentDirectory() + "../../../Sponsor.jpg");
                sponsor.Alignment = Element.ALIGN_CENTER;
                sponsor.GetBottom(0);
                doc.Add(sponsor);
                doc.NewPage();
            }
            doc.Close();

            Process.Start(sti + "/diplom.pdf");
        }

        private void btn_genererDiplom_Click(object sender, RoutedEventArgs e)
        {
            // De følgende udtryk er blot for demonstrationens skyld.
            // Herunder fyldes holdene med tilfældige data, for at kunne demonstrere rangering systemet
            Random r = new Random();
            foreach (Hold item in lv_holdListe.Items)
            {
                aktuelleHold = item;
                aktuelleHold.PointSum = 0;
                foreach (Kriterie itemx in aktuelleHold.Kriterier)
                {
                    itemx.Antal = r.Next(0, 100);
                    aktuelleHold.PointSum += itemx.Antal;
                }

            }

            // Fyld og sorter vores ListView samt andre Controls
            ListviewFiller(aktuelleKategori);
            SorterListView();
            UISkaber();
            
            // Ranger holdene efter Point
            int idx = 1;
            foreach (Hold item in lv_holdListe.Items)
            {
                item.Placering = idx;
                idx++;
            }

            GenererDiplom(lv_holdListe.Items);
        }

        private void Window_Closing(object sender, CancelEventArgs e)
        {
            int holdUdenPoint = 0;
            // Undersøg hvor mange hold som ikke har fået tildelt point endnu
            foreach (Kategori kat in aktuelleEvent.Kategorier)
            {
                foreach (Hold hold in kat.HListe)
                {
                    if (hold.ErTildeltPoint == false)
                    {
                        holdUdenPoint++;
                    }
                }
            }

            Kategori placeringsKonflikter = null;
            foreach (Kategori kat in aktuelleEvent.Kategorier)
            {
                int sidsteSum = 0;
                for (int i = 0; i < 10; i++)
                {
                    Hold hold = kat.HListe[i];
                    if (hold.PointSum == sidsteSum || (i == 9 && hold.PointSum == kat.HListe[10].PointSum))
                    {
                        placeringsKonflikter = kat;
                        break;
                    }
                }
            }

            if (holdUdenPoint > 0)
            {
                // Hvis nogle af holdene ikke har fået tildelt point, advares brugeren om konsekvenserne
                MessageBoxResult result = System.Windows.MessageBox.Show("Der er " + holdUdenPoint + " som ikke har fået tildelt point. Disse hold vil blive tildelt 0 point hvis du fortsætter.\r\n\r\nVil du fortsætte?", "Advarsel", MessageBoxButton.YesNo);

                if (result == MessageBoxResult.No)
                {
                    // Hvis der trykkes på annuller, lukkes vinduet ikke
                    e.Cancel = true;
                }
                else
                {
                    // Hvis der trykkes på OK, vil hvert hold der ikke har fået tildelt point blive tildet
                    // 0 point, hvorefter dataene bør gemmes
                    foreach (Kategori kat in aktuelleEvent.Kategorier)
                    {
                        foreach (Hold hold in kat.HListe)
                        {
                            if (hold.ErTildeltPoint == false)
                            {
                                foreach (Kriterie krit in hold.Kriterier)
                                {
                                    krit.Antal = 0;
                                }
                                hold.ErTildeltPoint = true;
                            }
                        }
                    }
                }
            }

            if (placeringsKonflikter != null)
            {
                MessageBoxResult result = System.Windows.MessageBox.Show("Der er konflikter i placeringen i top-10. Disse konflikter skal løses før du kan fortsætte.\r\nVil du lukke alligevel?", "Advarsel", MessageBoxButton.YesNo);
                if (result == MessageBoxResult.No)
                {
                    e.Cancel = true;
                }
            }
        }
    }
}